#include "../util/error.h"

#include <arpa/inet.h> // 用于处理网络地址转换和协议（如 inet_addr 和 htons）
#include <stdio.h>
#include <string.h>     // 提供字符串处理功能（如 bzero）
#include <sys/socket.h> // 提供 socket API 的功能
#include <unistd.h>

int main() {
    // 创建一个 TCP 套接字。AF_INET 表示 IPv4，SOCK_STREAM 表示流套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    errif(sockfd == -1, "socket creat error");

    // 设置超时时间为 5 秒
    struct timeval timeout;
    timeout.tv_sec  = 5;
    timeout.tv_usec = 0;
    if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) < 0) {
        close(sockfd);
        errif(sockfd == -1, "setsockopt error");
    }

    struct sockaddr_in serv_addr;                       // 包含了地址信息
    bzero(&serv_addr, sizeof(serv_addr));               // 清空结构体
    serv_addr.sin_family      = AF_INET;                // 使用 IPv4
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 本地地址
    serv_addr.sin_port = htons(8888); // 使用 htons 将端口号从主机字节序转换为网络字节序

    // 客户端通常不需要绑定套接字
    // errif(bind(sockfd, (sockaddr *)&serv_addr, sizeof(serv_addr)) == -1, "socket bind error");

    // 连接到指定的服务器地址和端口
    errif(connect(sockfd, (sockaddr *)&serv_addr, sizeof(serv_addr)) == -1, "socket connect error");

    while (true) {
        char buf[1024];
        bzero(&buf, sizeof(buf));
        scanf("%s", buf);
        ssize_t write_bytes = write(sockfd, buf, sizeof(buf));
        if (write_bytes == -1) {
            printf("socket already disconnected, can't write any more!\n");
            break;
        }
        bzero(&buf, sizeof(buf));
        ssize_t read_bytes = read(sockfd, buf, sizeof(buf));
        if (read_bytes > 0) {
            printf("message from server: %s\n", buf);
        } else if (read_bytes == 0) {
            printf("server socket disconnected!\n");
            break;
        } else if (read_bytes == -1) {
            close(sockfd);
            errif(true, "socket read error");
        }
    }

    close(sockfd);
    return 0;
}